package com.gupaoedu.design.observer.proxy.core;

import com.gupaoedu.design.observer.proxy.ISubject;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

/**
 * <p></p>
 *
 * @author Andy
 * @date 2018/3/21.
 */
public class EventListener implements InvocationHandler{
    private Map<Enum, Event> initParam = new HashMap<>();

    private ISubject subject;

    public EventListener(ISubject subject) {
        this.subject = subject;
    }

    public Object getProxy() {
        Class<? extends ISubject> clazz = this.subject.getClass();
        return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName = method.getName();
        EventType eventType = EventType.getStatusByName(methodName);
        trigger(eventType);
        method.invoke(this.subject, args);
        return null;
    }

    public void addListener(Enum eventType, Object target, Method method) {
        this.initParam.put(eventType, new Event(target, method));
    }

    protected void trigger(Enum eventType) {
        if (!this.initParam.containsKey(eventType)) {
            return;
        }

        Event e = this.initParam.get(eventType);
        e.setTrigger(eventType.toString());
        trigger(e);
    }

    private void trigger(Event e) {
        e.setSource(this);
        e.setTimes(System.currentTimeMillis());

        try {
            e.getCallback().invoke(e.getTarget(), e);
        } catch (IllegalAccessException e1) {
            e1.printStackTrace();
        } catch (InvocationTargetException e1) {
            e1.printStackTrace();
        }
    }
}
